Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit d6e7c6d1e9d42982f553b661dfd38cd7a7c44c4e


Parents : cbbe6b3
Author : Ivan <ivan@quad4.io>
Signature : Invalid signer <e46112d44649266d71fe2193e00a4710>, author is <ivan@quad4.io>
Date : 2026-07-07T23:06:37-05:00

feat(tests): add core runtime dependency tests for bleak in test_dependencies.py

Changes

2 files changed, 71 insertions(+), 0 deletions(-)


Diff

diff --git a/tests/backend/test_dependencies.py b/tests/backend/test_dependencies.py
new file mode 100644
index 00000000..f10c0c3b
--- /dev/null
+++ b/tests/backend/test_dependencies.py
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: 0BSD
+
+"""Core runtime dependency contract tests."""
+
+from __future__ import annotations
+
+import importlib.util
+from pathlib import Path
+
+import tomllib
+
+
+def _project_dependencies() -> list[str]:
+ root = Path(__file__).resolve().parents[2]
+ data = tomllib.loads((root / "pyproject.toml").read_text(encoding="utf-8"))
+ return list(data["project"]["dependencies"])
+
+
+def test_bleak_declared_in_pyproject():
+ assert any(dep.startswith("bleak") for dep in _project_dependencies())
+
+
+def test_bleak_importable():
+ assert importlib.util.find_spec("bleak") is not None

diff --git a/tests/backend/test_rns_config_management.py b/tests/backend/test_rns_config_management.py
index 0d866e69..ec13e176 100644
--- a/tests/backend/test_rns_config_management.py
+++ b/tests/backend/test_rns_config_management.py
@@ -134,3 +134,50 @@ def test_rns_config_file_path_is_normalized_to_directory(mock_rns, temp_dir):
assert app.reticulum_config_dir == config_dir
assert os.path.exists(config_file)
+
+
+def test_rns_config_disables_unsupported_ble_on_desktop_startup(
+ mock_rns,
+ temp_dir,
+ monkeypatch,
+):
+ """Startup repair must disable ble:// RNode entries when bleak is unavailable."""
+ from meshchatx.src.backend import rnode_support
+
+ config_dir = os.path.join(temp_dir, ".reticulum")
+ os.makedirs(config_dir, exist_ok=True)
+ config_file = os.path.join(config_dir, "config")
+ with open(config_file, "w", encoding="utf-8") as f:
+ f.write(
+ """[reticulum]
+enable_transport = False
+
+[interfaces]
+[[RNode BLE]]
+type = RNodeInterface
+interface_enabled = True
+port = ble://aa:bb:cc:dd:ee:ff
+[[RNode TCP]]
+type = RNodeInterface
+interface_enabled = True
+port = tcp://192.0.2.1:4242
+""",
+ )
+
+ monkeypatch.setattr(rnode_support, "_is_chaquopy_android", lambda: False)
+ monkeypatch.setattr(rnode_support, "desktop_ble_stack_available", lambda: False)
+ monkeypatch.setattr(rnode_support, "desktop_serial_stack_available", lambda: True)
+
+ with (
+ patch("meshchatx.meshchat.IdentityContext"),
+ patch("meshchatx.meshchat.WebAudioBridge"),
+ patch("meshchatx.meshchat.memory_log_handler"),
+ ):
+ ReticulumMeshChat(
+ identity=mock_rns["id_instance"],
+ storage_dir=temp_dir,
+ reticulum_config_dir=config_dir,
+ )
+
+ text = open(config_file, encoding="utf-8").read().lower()
+ assert text.count("interface_enabled = false") == 1


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────